package com.media.service.listener.record;

import com.media.cache.CacheUtil;
import com.media.common.Constants;
import com.media.common.ffmpeg.FFmpegError;
import com.media.common.ffmpeg.FFmpegUtil;
import com.media.config.MediaCaptorLiveConfig;
import com.media.pojo.CameraPojo;
import com.media.pojo.ResourceModel;
import com.media.service.listener.HandlerResourceListener;
import com.media.service.listener.RecordResourceListener;
import com.media.utils.DateUtils;
import com.media.utils.ToolUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * RTSP 转换 图片
 */
@Slf4j
@Service("rtspImageRecordService")
public class RtspImageRecordService implements RecordResourceListener {

    @Resource
    MediaCaptorLiveConfig mediaCaptorLiveConfig;

    @Override
    @Async("recordExecutor")
    public void record(ResourceModel resourceModel, HandlerResourceListener handlerListener) {
//     0 : 当前线程等待一秒 , 因为当前视频可能还没开始录制
        ToolUtils.sleep(300L);
//     1 : 取出摄像头对象
        CameraPojo cameraPojo = resourceModel.getCameraPojo();
//     2 :取出当前时间戳,作为视频的名称
        long videoName = CacheUtil.getCurrVideoName(String.valueOf(cameraPojo.getId()));
//     3 : 获取到RTSP地址
        String rtsp = FFmpegUtil.getRtsp(
                cameraPojo.getUsername(),
                cameraPojo.getPassword(),
                cameraPojo.getIp(),
                cameraPojo.getChannel(),
                cameraPojo.getStream());
//     4 : 图片要保存的路径  /home/resources/#{id}/image/2024-11-28/3412342342134/1410/1.jpg
        String imagePath = mediaCaptorLiveConfig.getResourcesSavePath() + "/" +
                cameraPojo.getId() + "/" +
                Constants.IMAGE + "/" +
                DateUtils.getDate() + "/" +
                videoName + "/" +
                DateUtils.parseDateToStr(DateUtils.HHMM, new Date()) + "/";
//     5 : 创建文件夹 / 删除上一个录制图片的进程
        ToolUtils.mkdirs(imagePath);
//     6 : 开始录制视频
        try {
//       6.1 : 生成ffmpeg命令
            List<String> commend = FFmpegUtil.rtspContinueToImage(rtsp, imagePath, 600 + "");
            InputStream inputStream;
            BufferedReader input;
            ProcessBuilder processBuilder = new ProcessBuilder(commend);
            processBuilder.redirectErrorStream(true);
            CacheUtil.closeImageMap(String.valueOf(cameraPojo.getId()));
            Process start = processBuilder.start();
//        6.2 : 获取到当前录制图片的进程,保存起来(便于关闭)
            WeakReference<Process> processWeakReference = new WeakReference<>(start);
            CacheUtil.putImageMap(String.valueOf(cameraPojo.getId()), processWeakReference);
            inputStream = start.getInputStream();
            input = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = input.readLine()) != null) {
                log.debug("ffmpeg input={}", line);
                for (String e : FFmpegError.getErrors()) {
                    if (Optional.of(line).filter(r -> r.contains(e)).isPresent()) {
                        log.debug("ffmpeg continue image error={}", line);
                    }
                }
            }
        } catch (Exception e) {
            log.error("持续录制图片,出现错误 : {}", resourceModel, e);
        } finally {
//            关闭摄像头当前的推流图片(录制完成/出现错误 : 关闭)
            CacheUtil.closeImageMap(String.valueOf(cameraPojo.getId()));
        }
//      7. 图片录制完毕
        log.info("持续录制图片录制成功!! {}", imagePath);
//      处理图片
        if (handlerListener != null) {
            handlerListener.handler(resourceModel);
        }
    }
}
